package main

import (
	"fmt"
	"go-xorm-01/utils"
	"time"
	"xorm.io/xorm"
	"xorm.io/xorm/log"
	"xorm.io/xorm/names"
)

var engine *xorm.Engine

func main() {
	SnakeMapper()
	//insetManyUser(engine)
	//engine.DumpAllToFile("demo06-update/demo01-update/sql.sql")
	updateUser(engine)
}

func updateUser(engine *xorm.Engine) {
	//更新数据使用Update方法，Update方法的第一个参数为需要更新的内容，可以为一个结构体指针或者一个Map[string]interface{}类型。
	//当传入的为结构体指针时，只有非空和0的field才会被作为更新的字段。当传入的为Map类型时，key为数据库Column的名字，value为要更新的内容。
	//
	//Update方法将返回两个参数，第一个为 更新的记录数，需要注意的是 SQLITE 数据库返回的是根据更新条件查询的记录数而不是真正受更新的记录数。
	var user UserUpdate = UserUpdate{
		Username: "tristan--up",
	}
	update, _ := engine.ID(1).Update(&user)
	fmt.Println(update)

	//这里需要注意，Update会自动从user结构体中提取非0和非nil得值作为需要更新的内容，因此，如果需要更新一个值为0，则此种方法将无法实现，因此有两种选择：

	//1.通过添加Cols函数指定需要更新结构体中的哪些值，未指定的将不更新，指定了的即使为0也会更新。
	var user1 UserUpdate = UserUpdate{
		GroupId: 0,
	}
	affected, _ := engine.ID(1).Cols("group_id").Update(&user1)
	fmt.Println(affected)
	//2.通过传入map[string]interface{}来进行更新，但这时需要额外指定更新到哪个表，因为通过map是无法自动检测更新哪个表的。
	affected1, _ := engine.Table(new(UserUpdate)).ID(2).Update(map[string]interface{}{"group_id": 0})
	fmt.Println(affected1)

	//有时候希望能够指定必须更新某些字段，而其它字段根据值的情况自动判断，可以使用 MustCols 来组合 Update 使用。
	//engine.ID(1).MustCols("username").Update(&user)

	//另外，如果需要更新所有的字段，可以使用 AllCols()。
	//engine.ID(3).AllCols().Update(&user)
}

func SnakeMapper() {
	engine = utils.GenerateEngine()
	engine.SetMapper(names.SnakeMapper{}) // SnakeMapper 【默认】
	err := engine.Sync2(new(UserUpdate))
	if err != nil {
		fmt.Printf("err:%v", err)
	}
	engine.ShowSQL(true)
	engine.SetLogLevel(log.LOG_DEBUG)

}

func insetManyUser(engine *xorm.Engine) {
	groupOne := make([]*UserUpdate, 0)
	for i := 0; i < 5; i++ {
		groupOne = append(groupOne, &UserUpdate{
			Username: fmt.Sprintf("zhangsan-%d", i),
			Password: fmt.Sprintf("123456-%d", i),
			GroupId:  1,
			Rank:     i,
		})
	}
	engine.Insert(groupOne)

	groupTwo := make([]*UserUpdate, 0)
	for i := 0; i < 3; i++ {
		groupTwo = append(groupTwo, &UserUpdate{
			Username: fmt.Sprintf("lisi-%d", i),
			Password: fmt.Sprintf("00000-%d", i),
			GroupId:  2,
			Rank:     i,
		})
	}
	engine.Insert(groupTwo)

}

type JsonTime time.Time

func (j JsonTime) MarshalJSON() ([]byte, error) {
	return []byte(`"` + time.Time(j).Format("2006-01-02 15:04:05") + `"`), nil
}

type UserUpdate struct {
	Id        int64     `xorm:"pk autoincr"`                                              //指定列名 ，默认id
	Username  string    `xorm:"varchar(25) notnull unique(u_p) 'username' comment('姓名')"` //复合唯一索引
	Password  string    `xorm:"varchar(25) notnull unique(u_p) 'password' comment('密码')"` //复合唯一索引
	TimeOne   time.Time `xorm:"created"`
	TimeTwo   JsonTime  `xorm:"created"`
	TimeThree int64     `xorm:"created"`
	GroupId   int64
	Rank      int
	Version   int `xorm:"version"`
}
